#include "StdAfx.h"
#include "PasswordManager.h"

CPasswordManager::CPasswordManager(void)
{
}

CPasswordManager::~CPasswordManager(void)
{
}
BOOL CPasswordManager::Add(const CPasswordProfile& pswPf)
{
	pSQLStatement.Release();
	static LPCWSTR szSQL = L"insert into km_password(classid,title,username,password,address,remark,timecreated,timeedit,timeAccess,"
		L"timeExpire,AttachName,icon,attachcontent,aclen,MasterID) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
	if(pswPf.m_strTitle.IsEmpty() || pswPf.m_strUserName.IsEmpty() || pswPf.m_strPassword.IsEmpty())
		return FALSE;
	
	//m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,pswPf.m_nClassID);
	pSQLStatement->Bind(2,pswPf.m_strTitle);
	pSQLStatement->BindBlob(3,(char*)pswPf.m_pUserName,pswPf.m_nUNLen );
	//pSQLStatement->Bind(3,pswPf.m_strUserName);
	//pSQLStatement->Bind(4,pswPf.m_strPassword);
	pSQLStatement->BindBlob(4,(char*)pswPf.m_pPassword,pswPf.m_nPswLen );
	pSQLStatement->Bind(5,pswPf.m_strAddress);
	pSQLStatement->Bind(6,pswPf.m_strRemark);
	pSQLStatement->Bind(7,(int)pswPf.m_tCreate.GetTime());
	pSQLStatement->Bind(8,(int)pswPf.m_tEdit.GetTime());
	pSQLStatement->Bind(9,(int)pswPf.m_tAccess.GetTime());
	pSQLStatement->Bind(10,(int)pswPf.m_tExpire.GetTime());
	pSQLStatement->Bind(11,pswPf.m_strAttachName);
	pSQLStatement->Bind(12,pswPf.m_nIcon);
	if(pswPf.m_nACLen == 0)
		pSQLStatement->BindZeroBlob(13,0);
	else
		pSQLStatement->BindBlob(13,(char*)pswPf.m_pAttachContent,pswPf.m_nACLen );
	pSQLStatement->Bind(14,pswPf.m_nACLen);
	pSQLStatement->Bind(15,pswPf.m_nMasterID);

	return SUCCEEDED(pSQLStatement->ExecuteUpdate());

	/*if(Res)
	{
		m_pDB->CommitTransaction();;
		return 63;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 64;
	}*/
}
int CPasswordManager::Delete(const int nID)
{
	static LPCWSTR szSQL = L"delete from km_password where id=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,nID);
	
	BOOL Res = SUCCEEDED(pSQLStatement->ExecuteUpdate());

	if(Res)
	{
		m_pDB->CommitTransaction();
		return 65;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 66;
	}
}
int CPasswordManager::Update(const CPasswordProfile& pswPf)
{
	static LPCWSTR szSQL = L"update km_password set title=?,username=?,password=?,address=?,remark=?,timeedit=?,timeAccess=?,"
		L"timeExpire=?,AttachName=?,icon=?,attachcontent=?,aclen=? where id=?;";
	if(pswPf.m_strTitle.IsEmpty() || pswPf.m_strUserName.IsEmpty() || pswPf.m_strPassword.IsEmpty())
		return 62;
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);


	pSQLStatement->Bind(1,pswPf.m_strTitle);
	pSQLStatement->BindBlob(2,(char*)pswPf.m_pUserName,pswPf.m_nUNLen );
	//pSQLStatement->Bind(3,pswPf.m_strUserName);
	//pSQLStatement->Bind(4,pswPf.m_strPassword);
	pSQLStatement->BindBlob(3,(char*)pswPf.m_pPassword,pswPf.m_nPswLen );
	pSQLStatement->Bind(4,pswPf.m_strAddress);
	pSQLStatement->Bind(5,pswPf.m_strRemark);
	pSQLStatement->Bind(6,(int)pswPf.m_tEdit.GetTime());
	pSQLStatement->Bind(7,(int)pswPf.m_tAccess.GetTime());
	pSQLStatement->Bind(8,(int)pswPf.m_tExpire.GetTime());
	pSQLStatement->Bind(9,pswPf.m_strAttachName);
	pSQLStatement->Bind(10,pswPf.m_nIcon);
	if(pswPf.m_nACLen == 0)
		pSQLStatement->BindZeroBlob(11,0);
	else
		pSQLStatement->BindBlob(11,(char*)(pswPf.m_pAttachContent),pswPf.m_nACLen );
	pSQLStatement->Bind(12,pswPf.m_nACLen);
	pSQLStatement->Bind(13,pswPf.m_nID);

	BOOL Res = SUCCEEDED(pSQLStatement->ExecuteUpdate());

	if(Res)
	{
		m_pDB->CommitTransaction();;
		return 67;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 68;
	}
}
PswPfList* CPasswordManager::Get(const int nMasterID)
{
	static LPCWSTR szSQL = L"select id,title,username,password,address,remark,timecreated,timeedit,timeAccess,"
		L"timeExpire,AttachName,icon,aclen,attachcontent,ClassID from km_password where MasterID=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,nMasterID);
	CComPtr<Skylark::ISQLiteComResultSet3> pRs;
	HRESULT hr = pSQLStatement->ExecuteQuery(&pRs);
	if(!SUCCEEDED(hr) || pRs->IsEof())
		return NULL;
	PswPfList* list = new PswPfList();
	while(!pRs->IsEof())
	{
		CPasswordProfile* pswPf =new CPasswordProfile();
		pswPf->m_nID = pRs->GetInt(0);
		pswPf->m_strTitle = pRs->GetAsString(1);
		int nLen = pRs->GetBlobBytes(2);
		pswPf->m_pUserName = new BYTE[nLen];
		pRs->GetBlob(2,(char*)(pswPf->m_pUserName),nLen);
		pswPf->m_nUNLen = nLen;
		nLen = pRs->GetBlobBytes(3);
		pswPf->m_pPassword = new BYTE[nLen];
		pRs->GetBlob(3,(char*)(pswPf->m_pPassword),nLen);
		pswPf->m_nPswLen = nLen;
		/*pswPf->m_strUserName = pRs->GetAsString(3);
		pswPf->m_strPassword = pRs->GetAsString(4);*/
		pswPf->m_strAddress = pRs->GetAsString(4);
		pswPf->m_strRemark = pRs->GetAsString(5);
		pswPf->m_tCreate = CTime(pRs->GetInt(6));
		pswPf->m_tEdit = CTime(pRs->GetInt(7));
		pswPf->m_tAccess = CTime(pRs->GetInt(8));
		pswPf->m_tExpire = CTime(pRs->GetInt(9));
		pswPf->m_strAttachName = pRs->GetAsString(10);
		pswPf->m_nIcon = pRs->GetInt(11);
		nLen = pRs->GetInt(12);
		if(nLen > 0)
		{
			pswPf->m_nACLen = nLen;
			pswPf->m_pAttachContent = new BYTE[nLen];
			pRs->GetBlob(13,(char*)(pswPf->m_pAttachContent),nLen);
		}
		else
		{
			pswPf->m_pAttachContent = NULL;
			pswPf->m_nACLen = 0;
		}
		pswPf->m_nClassID = pRs->GetInt(14);
		pswPf->m_nMasterID = nMasterID;
		list->AddTail(pswPf);
		pRs->NextRow();
	}
	return list;
}
int CPasswordManager::MoveTo(const int iClassID,const int iID)
{
	static LPCWSTR szSQL = L"update km_password set classid=? where id=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,iClassID);
	pSQLStatement->Bind(2,iID);
	BOOL Res = SUCCEEDED(pSQLStatement->ExecuteUpdate());

	if(Res)
	{
		m_pDB->CommitTransaction();
		return 10;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 11;
	}
}
int CPasswordManager::SetAccess(const int nID)
{
	static LPCWSTR szSQL = L"update km_password set timeaccess=? where id=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,(int)CTime::GetCurrentTime().GetTime());
	pSQLStatement->Bind(2,nID);
	BOOL Res = SUCCEEDED(pSQLStatement->ExecuteUpdate());

	if(Res)
	{
		m_pDB->CommitTransaction();
		return 10;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 11;
	}
}


BOOL CPasswordManager::Add(const CPwMaster& pswPf)
{
	pSQLStatement.Release();
	static LPCWSTR szSQL = L"insert into KM_PWMaster(Type,MasterName,PswAndKey,KeyFile,MasterSeed,EncryptionIV,ContentsHash,MasterSeed2,KeyEncRounds)"
		L"values (?,?,?,?,?,?,?,?,?);";
	if(pswPf.m_Name.IsEmpty())
		return FALSE;
	
	//m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,pswPf.m_Type);
	pSQLStatement->Bind(2,pswPf.m_Name);
	pSQLStatement->Bind(3,pswPf.m_PswAndKey);
	pSQLStatement->Bind(4,pswPf.m_KeyFile);
	pSQLStatement->BindBlob(5,(char*)pswPf.m_MasterSeed,16);
	pSQLStatement->BindBlob(6,(char*)pswPf.m_EncryptionIV,16);
	pSQLStatement->BindBlob(7,(char*)pswPf.m_ContentsHash,32);
	pSQLStatement->BindBlob(8,(char*)pswPf.m_MasterSeed2,32);
	pSQLStatement->Bind(9,pswPf.m_KeyEncRounds);

	return SUCCEEDED(pSQLStatement->ExecuteUpdate());
	
	/*if(Res)
	{
		m_pDB->CommitTransaction();;
		return 63;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 64;
	}*/
}
int CPasswordManager::DeleteMaster(const int nID)
{
	static LPCWSTR szSQL = L"delete from KM_PWMaster where id=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,nID);
	
	BOOL Res = SUCCEEDED(pSQLStatement->ExecuteUpdate());

	if(Res)
	{
		m_pDB->CommitTransaction();
		return 65;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 66;
	}
}
BOOL CPasswordManager::Update(const CPwMaster& pswPf)
{
	pSQLStatement.Release();
	static LPCWSTR szSQL = L"update KM_PWMaster set MasterName=?,PswAndKey=?,KeyFile=?,MasterSeed=?,EncryptionIV=?,ContentsHash=?,MasterSeed2=?,"
		L"KeyEncRounds=? where id=?;";
	if(pswPf.m_Name.IsEmpty() || pswPf.m_Type.IsEmpty())
		return FALSE;

	//m_pDB->BeginTransaction();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,pswPf.m_Name);
	pSQLStatement->Bind(2,pswPf.m_PswAndKey);
	pSQLStatement->Bind(3,pswPf.m_KeyFile);
	pSQLStatement->BindBlob(4,(char*)pswPf.m_MasterSeed,16);
	pSQLStatement->BindBlob(5,(char*)pswPf.m_EncryptionIV,16);
	pSQLStatement->BindBlob(6,(char*)pswPf.m_ContentsHash,32);
	pSQLStatement->BindBlob(7,(char*)pswPf.m_MasterSeed2,32);
	pSQLStatement->Bind(8,pswPf.m_KeyEncRounds);
	pSQLStatement->Bind(9,pswPf.m_nID);

	return SUCCEEDED(pSQLStatement->ExecuteUpdate());

	/*if(Res)
	{
		m_pDB->CommitTransaction();;
		return 67;
	}
	else
	{
		m_pDB->RollbackTransaction();
		return 68;
	}*/
}
CPwMaster* CPasswordManager::Get(const CString strName)
{
	static LPCWSTR szSQL = L"select ID,Type,MasterName,PswAndKey,KeyFile,MasterSeed,EncryptionIV,ContentsHash,MasterSeed2,KeyEncRounds from KM_PwMaster where MasterName=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,strName);
	CComPtr<Skylark::ISQLiteComResultSet3> pRs;
	HRESULT hr = pSQLStatement->ExecuteQuery(&pRs);
	if(!SUCCEEDED(hr) || pRs->IsEof())
		return NULL;
	CPwMaster* pwm = new CPwMaster();
	pwm->m_Update = TRUE;
	if(!pRs->IsEof())
	{
		pwm->m_nID =  pRs->GetInt(0);
		pwm->m_Type = pRs->GetAsString(1);
		pwm->m_Name = pRs->GetAsString(2);
		pwm->m_PswAndKey = pRs->GetInt(3);
		pwm->m_KeyFile = pRs->GetAsString(4);
		pRs->GetBlob(5,(char*)pwm->m_MasterSeed,16);
		pRs->GetBlob(6,(char*)pwm->m_EncryptionIV,16);
		pRs->GetBlob(7,(char*)pwm->m_ContentsHash,32);
		pRs->GetBlob(8,(char*)pwm->m_MasterSeed2,32);
		
		pwm->m_KeyEncRounds = pRs->GetInt(9);
	}
	return pwm;
}

int CPasswordManager::GetNextID()
{
	static LPCWSTR szSQL = L"select max(ID) from KM_PwMaster;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);
	CComPtr<Skylark::ISQLiteComResultSet3> pRs;
	HRESULT hr = pSQLStatement->ExecuteQuery(&pRs);
	if(!SUCCEEDED(hr) || pRs->IsEof())
		return 1;
	if(!pRs->IsEof())
		return pRs->GetInt(0) + 1;
	else
		return 1;
}

BOOL CPasswordManager::IsExist(const CString strName)
{
	static LPCWSTR szSQL = L"select ID from KM_PwMaster where MasterName=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);
	pSQLStatement->Bind(1,strName);
	CComPtr<Skylark::ISQLiteComResultSet3> pRs;
	HRESULT hr = pSQLStatement->ExecuteQuery(&pRs);
	if(!SUCCEEDED(hr) || pRs->IsEof())
		return FALSE;
	if(!pRs->IsEof())
		return TRUE;
	else
		return FALSE;
}
PwMasterList* CPasswordManager::GetList(const CString strType)
{
	static LPCWSTR szSQL = L"select ID,Type,MasterName,PswAndKey,KeyFile from KM_PwMaster where Type=?;";
	CComPtr<ISQLiteComStatement3> pSQLStatement;
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);

	pSQLStatement->Bind(1,strType);
	CComPtr<Skylark::ISQLiteComResultSet3> pRs;
	HRESULT hr = pSQLStatement->ExecuteQuery(&pRs);
	if(!SUCCEEDED(hr) || pRs->IsEof())
		return NULL;
	PwMasterList* list = new PwMasterList();
	while(!pRs->IsEof())
	{
		CPwMaster* pwm = new CPwMaster();
		pwm->m_nID =  pRs->GetInt(0);
		pwm->m_Type = pRs->GetAsString(1);
		pwm->m_Name = pRs->GetAsString(2);
		pwm->m_PswAndKey = pRs->GetInt(3);
		pwm->m_KeyFile = pRs->GetAsString(4);
		list->AddTail(pwm);
		pRs->NextRow();
	}
	return list;
}

void CPasswordManager::BeginSave()
{
	m_pDB->BeginTransaction();
}
void CPasswordManager::EndSave(BOOL bCommit)
{
	if(bCommit)
		m_pDB->CommitTransaction();
	else
		m_pDB->RollbackTransaction();
}
BOOL CPasswordManager::Save(const CPwMaster& pswPf)
{
	BOOL bRes = FALSE;
	if(pswPf.m_Update)
		bRes = this->Update(pswPf);
	else
		bRes = this->Add(pswPf);
	if(!bRes)
		return bRes;
	static LPCWSTR szSQL = L"delete  from KM_Password where MasterId=?;";
	pSQLStatement.Release();
	m_pDB->PrepareStatement(szSQL,&pSQLStatement);
	pSQLStatement->Bind(1,pswPf.m_nID);
	return SUCCEEDED(pSQLStatement->ExecuteUpdate());

}